//
//  WLUploadSocketWorker.m
//  WanLian
//
//  Created by 123456 on 2019/1/4.
//  Copyright © 2019 wanlian. All rights reserved.
//

#import "WLUploadWorker.h"
#import "WLFileRequest.h"
#import "WLSocketBlockWorker.h"
#import "WLRecallModel.h"
#import "WLFileTransportHeadModel.h"
//extern BOOL flag;
@implementation WLUploadWorker
- (void)suspend {
    [super suspend];
    for (WLSocketBlockWorker *blockWorker in self.requestModel.blockWorkArr) {
        [blockWorker suspend];
    }
    [self.requestModel.blockWorkArr removeAllObjects];
    [self.requestModel.blockModelArr removeAllObjects];
}

- (void)cancel {
    [super cancel];
    for (WLSocketBlockWorker *blockWorker in self.requestModel.blockWorkArr) {
        [blockWorker cancel];
    }
    [self.requestModel.blockWorkArr removeAllObjects];
    [self.requestModel.blockModelArr removeAllObjects];
}

- (void)resume {
    [super resume];
}

- (WLSocketWorker *)configWorkerWithFIFOModel:(WLFileRequest *)model
                         progress:(void (^)(float))progress
                          success:(void (^)(NSDictionary *successDict))success
                          failure:(void (^)(NSString *errorMsg, NSInteger errorTag))failure
                            error:(void (^)(NSError *error))err {
    self.requestModel = model;
    self.recallModel = [WLRecallModel createWithProgressBlock:progress successBlock:success faliureBlock:failure errorBlock:err];
    self.currentSocket = [self Client_init];
    self.requestModel.workingState = WLWorkingStateReadySend;
    return self;
}


- (void)sendFileInfo:(GCDAsyncSocket *)socket_fd fileModel:(WLFileRequest *)model withType:(NSString *)type{
    NSData * fileInfo = [model getFileTransmitHeadDataWithType:type];
    NSData *headData = [self configHeadProtocolWithData:fileInfo];
    [socket_fd writeData:headData withTimeout:SocketTimeOut tag:WriteFileHeadTag];
}

#pragma mark - GCDAsyncSocketDelegate
/**
 * Called when a socket connects and is ready for reading and writing.
 * The host parameter will be an IP address, not a DNS name.
 **/
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    [super socket:sock didConnectToHost:host port:port];
    if (sock == self.currentSocket) {
        [self sendFileInfo:sock fileModel:self.requestModel withType:DEVICE_FILE_UPLOAD_HEAD];
    }
}

/**
 * Called when a socket has completed reading the requested data into memory.
 * Not called if there is an error.
 **/
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    [super socket:sock didReadData:data withTag:tag];
    if (tag == WriteFileHeadTag) {
        if (self.parser == nil) {
            WLWkSelf
            self.parser = [[WLSocketPacketParser alloc] initWithParserResultBlock:^(NSDictionary *msgDict, NSData *fileData, WLParserStatus status) {
                if (status == WLParserStatusSucess) {
                    NSDictionary *dictionary = msgDict;
                    WLSocketModel *messageModel = [WLSocketModel mj_objectWithKeyValues:dictionary];
                    if ([dictionary[@"content"] isKindOfClass:[NSString class]]) {
                        NSDictionary *contentDict = [dictionary[@"content"] jsonObject];
                        if ([contentDict[@"resultCode"] integerValue] ==1) {
                            if ([messageModel.type isEqualToString:DEVICE_FILE_UPLOAD_CHECK]) {
                                weakSelf.requestModel.currentSize = [contentDict[@"currentSize"] longValue];
                                if (weakSelf.requestModel.currentSize == weakSelf.requestModel.fileTotalBytes) {
                                    if (weakSelf.recallModel.successBlock) {
                                        weakSelf.recallModel.successBlock([NSDictionary dictionary]);
                                        return ;
                                    }
                                }
                                [weakSelf distributeTaskWithSourceId:0 fileModel:self.requestModel];
                            }
                        }else {
                            if (weakSelf.recallModel.faliureBlock) {
                                weakSelf.recallModel.faliureBlock(contentDict[@"resultMsg"], FileTransportErrorTypeServer);
                            }
                        }
                    }
                } else {
                    if (weakSelf.recallModel.faliureBlock) {
                        weakSelf.recallModel.faliureBlock(@"数据解析错误", FileTransportErrorTypeDataParsaringError);
                    }
                }
            }];
        }
        
        [self.parser readData:data withSocket:sock tag:tag];
//        [sock readDataWithTimeout:SocketTimeOut tag:tag];
    }
}


/**
 * Called when a socket has completed writing the requested data. Not called if there is an error.
 **/
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
    [super socket:sock didWriteDataWithTag:tag];
     if (tag == WriteFileHeadTag){
        [sock readDataWithTimeout:SocketTimeOut tag:WriteFileHeadTag];
    }
}


- (void)recycleSocket {
    [self.currentSocket disconnect];
}
- (void)distributeTaskWithSourceId:(int)sourceId fileModel:(WLFileRequest *)model{
    [self recycleSocket];
    
    [model fonfigBlockInfo];//配置分块信息
//    if (self.requestModel.blockWorkArr.count <= 0 && self.requestModel.blockWorkArr.count <= 0) {
//
//    }
    NSMutableArray *blockModelArr = [NSMutableArray array];
    NSMutableArray *muWorkerArr = [NSMutableArray array];
    model.blockModelArr = blockModelArr;
    model.blockWorkArr = muWorkerArr;
    for (int i = 0; i < model.blockCount; i ++) {
        WLSocketBlockWorker *worker = [[WLSocketBlockWorker alloc] init];
        WLFileTransportHeadModel *blockModel = [WLFileTransportHeadModel createWithTaskModel:model index:i sourceId:sourceId];
        worker.curHeadModel = blockModel;
        worker.requestModel = model;
        [worker Client_init];
        [blockModelArr addObject:blockModel];
        WLWkSelf
        worker.fileTransportingBlock = ^{
            [weakSelf dealWithTransporting];
        };
        worker.fileTransportCompleteBlock = ^{
            [weakSelf dealWithFileTransportCompleteBlock];
        };
        worker.fileTransportFailureBlock = self.recallModel.faliureBlock;
        [worker resume];
        [muWorkerArr addObject:worker];
    }
    
}

- (void)dealWithTransporting {
    long sendedTotalSize = 0;
    for (WLFileTransportHeadModel *blockModel in self.requestModel.blockModelArr) {
        sendedTotalSize += blockModel.sendedSize;
    }
    sendedTotalSize += self.requestModel.currentSize;
    if (self.recallModel.progressBlcok) {
        float process = sendedTotalSize * 1.0 / self.requestModel.fileTotalBytes;
        self.recallModel.progressBlcok(process);
    }
}

- (void)dealWithFileTransportCompleteBlock {
    for (WLSocketWorker *worker in self.requestModel.blockWorkArr) {
        [worker cancel];
    }
    [self.requestModel.blockModelArr removeAllObjects];
    [self.requestModel.blockWorkArr removeAllObjects];
    //移除数据库多个worker
    if (self.fileTransportCompleteBlock) {
        self.fileTransportCompleteBlock();
    }
    
    if (self.recallModel.successBlock) {
        self.recallModel.successBlock([NSDictionary dictionary]);
    }
}

- (void)dealloc {
    [self clearTimer];
}

@end
